#include <iostream>
#include <jsoncpp/json/json.h>
#include <string>
#include <sstream>
#include <memory>

// Json 的数据类型包括对象，数组，字符串，数字等。
// • 对象：使⽤花括号 {} 括起来的表⽰⼀个对象
// • 数组：使⽤中括号 [] 括起来的表⽰⼀个数组
// • 字符串：使⽤常规双引号 "" 括起来的表⽰⼀个字符串
// • 数字：包括整形和浮点型，直接使用
// Jsoncpp 库主要是⽤于实现 Json 格式数据的序列化和反序列化，它实现了将多个数据对象组织成
// 为 json 格式字符串，以及将 Json 格式字符串解析得到多个数据对象的功能。

//Json::Value类:中间存储类
//Json::StreamWriter类:用于序列化
//    class JSON_API StreamWriter {
//     virtual int write(Value const& root, std::ostream* sout) = 0;
//    }
//    class JSON_API StreamWriterBuilder : public StreamWriter::Factory {//工厂类
//     virtual StreamWriter* newStreamWriter() const;
//    }

//Json::CharReader类:用于反序列化
//    class JSON_API CharReader {
//  virtual bool parse(char const* beginDoc, char const* endDoc, 
//     Value* root, std::string* errs) = 0;
//    }
//    class JSON_API CharReaderBuilder : public CharReader::Factory {
//     virtual CharReader* newCharReader() const;
//    }

//序列化
bool serialize(const Json::Value & val,std::string & body)
{
    std::stringstream ss;//字符串流
    Json::StreamWriterBuilder swb;//先构建一个工厂类对象
    std::unique_ptr<Json::StreamWriter> sw (swb.newStreamWriter());//通过工厂类对象来生产派生类对象
    int n = sw->write(val,&ss);
    if(n !=0)//出错
    {
        std::cout<<"Json serialize failed"<<std::endl;
        return false;
    }
    body = ss.str();
    return true;
}


//反序列化
bool unserialize(const std::string & body,Json::Value & val)
{
    Json::CharReaderBuilder crb;//先构建一个工厂类对象
    std::unique_ptr<Json::CharReader> cr(crb.newCharReader());
    std::string err;//错误信息
    bool ret = cr->parse(body.c_str(),body.c_str()+body.size(),&val,&err);
    if(!ret)
    {
        std::cout<<"Json unserialize failed:"<<err<<std::endl;
        return false;
    }
    return true;
}

int main()
{
    const char * name = "小明";
    int age = 18;
    const char * sex = "男";
    float score[3] = {22.2,33.3,55.5};
    Json::Value student;
    student["姓名"] = name;
    student["年龄"] = age;
    student["性别"] = sex;
    student["成绩"].append(score[0]);
    Json::Value val;
    val["书籍"] = "西游记";
    val["运动"] = "打篮球";
    student["爱好"] = val;
    student["成绩"].append(score[1]);
    student["成绩"].append(score[2]);
    std::string body;
    serialize(student,body);
    std::cout<<"序列化后"<<std::endl;
    std::cout<<body<<std::endl;
    std::cout<<"反序列化后"<<std::endl;
    Json::Value res;
    unserialize(body,res);
    std::cout<<"姓名:"<<res["姓名"].asString()<<std::endl;
    std::cout<<"年龄:"<<res["年龄"].asInt()<<std::endl;
    std::cout<<"性别:"<<res["性别"].asString()<<std::endl;
    std::cout<<"书籍:"<<res["爱好"]["书籍"].asString()<<std::endl;
    std::cout<<"运动:"<<res["爱好"]["运动"].asString()<<std::endl;
    int sz = res["成绩"].size();
    for(int i = 0;i<sz;i++)
    {
        std::cout<<"成绩:"<<res["成绩"][i].asFloat()<<std::endl;
    }
    return 0;
}
